package genetica.cruce;

import genetica.cromosomas.Cromosoma;
import genetica.cromosomas.genes.Gen;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

public class CruceOX extends AlgoritmoCruce {

	public CruceOX(double pCruce) {
		super(pCruce);
	}

	@Override
	public void cruce(Cromosoma prog1, Cromosoma prog2) {
		
		Random generador = new Random();
		int posCruce1 = (generador.nextInt(prog1.getGenes().size()));
		int posCruce2 = (generador.nextInt(prog1.getGenes().size()));
		if(posCruce1 > posCruce2){
			int temp = posCruce1;
			posCruce1 = posCruce2;
			posCruce2 = temp;
		}
		int tam = prog1.getGenes().size();
		// inicializo los hijos
		Gen[] desc1 = new Gen[prog1.getGenes().size()];
		Gen[] desc2 = new Gen[prog1.getGenes().size()];

		int a1, a2;

		// Arrays de parejas fijas
		ArrayList<Gen> fijosProg1 = new ArrayList<Gen>();
		ArrayList<Gen> fijosProg2 = new ArrayList<Gen>();

		// Tenemos en los descendientes los que estan entre las posiciones de cruce
		for (int i = posCruce1; i < posCruce2; i++) {
			desc1[i] = prog2.getGenes().get(i);
			desc2[i] = prog1.getGenes().get(i);
			fijosProg1.add((prog2.getGenes().get(i)));
			fijosProg2.add((prog1.getGenes().get(i)));
		}
		
		for (int i = posCruce2, j = posCruce2, k = posCruce2; i != posCruce1;i = (i+1) % tam, j = (j+1) % tam, k = (k+1) % tam){
			i %= tam;
			j %= tam;
			k %= tam;
			Gen g1 = prog1.getGenes().get(j); 
			while (fijosProg1.contains(g1)){
				j = (j+1) % tam;
				g1 = prog1.getGenes().get(j); 
			}
			desc1[i] = g1;
			fijosProg1.add(g1);
			
			Gen g2 = prog2.getGenes().get(k);
			while (fijosProg2.contains(g2)){
				k = (k+1) % tam;
				g2 = prog2.getGenes().get(k); 
			}
			desc2[i] = g2;
			fijosProg2.add(g2);
		}
		if (desc1[0] == null)
			return;
		prog1.setGenes(new ArrayList<Gen>(Arrays.asList(desc1)));
		prog2.setGenes(new ArrayList<Gen>(Arrays.asList(desc2)));

	}

	@Override
	public String toString() {
		return "Algoritmo de cruce OX";
	}
}
